-
Notifications
You must be signed in to change notification settings - Fork 99
Add ListResource RPC #1157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ListResource RPC #1157
Conversation
6414d9d to
ed02781
Compare
56424fa to
d5d9cb5
Compare
af2d8f7 to
380b706
Compare
380b706 to
ce0467f
Compare
| } | ||
|
|
||
| if _, ok := s.resourceFuncs[typeName]; !ok { | ||
| resourceFuncs, _ := s.ResourceFuncs(ctx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cross-ref: #1152 (comment)
This feels more robust. And removes the need for "call X before Y" comments.
| Results iter.Seq[ListResult] | ||
| } | ||
|
|
||
| func ListResultError(summary string, detail string) ListResult { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: add a doc comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it's not a "publicly" exported field, no need to add a doc comment unless you feel this helper needs more explanation for maintainers.
Although I'm wondering if this function even needs to be exported (or even exist, it's only used once ATM, maybe it will be used more later?)
| if _, ok := resourceFuncs[typeName]; !ok { | ||
| s.listResourceFuncsDiags.AddError( | ||
| "ListResource Type Defined without a Matching Managed Resource Type", | ||
| fmt.Sprintf("The %s ListResource type name was returned, but no matching managed Resource type was defined. ", typeName)+ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO, after this PR: we want the flexibility for a list resource in Framework to work with a managed resource type in SDKv2. So we'll revisit this logic.
| return ListRequestErrorDiagnostics(ctx, allDiags...) | ||
| } | ||
|
|
||
| resourceSchema, diags := s.FrameworkServer.ResourceSchema(ctx, protoReq.TypeName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO, after this PR: we want the flexibility for a list resource in Framework to work with a managed resource type in SDKv2. So we'll revisit this logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I'd think since fwserver doesn't need these values, then this would just be something could be a nil all the way through to the List call. Where the provider developer would then just construct tfsdk.Resource themselves? (which needs to happen anyways?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the fun part. As in #1157 (comment), good enough for this PR while under construction for SDKv2 considerations.
As I piece this together, I see that a provider developer typically writes:
resp.State.Set(ctx, &data)
and this works because fwserver has pre-set resp.State.Schema:
terraform-plugin-framework/internal/fwserver/server_readresource.go
Lines 99 to 104 in a7f8748
| readResp := resource.ReadResponse{ | |
| State: tfsdk.State{ | |
| Schema: req.CurrentState.Schema, | |
| Raw: req.CurrentState.Raw.Copy(), | |
| }, | |
| } |
This is the one reason that fwserver.ListResource is interested in the resource schema and resource identity schema.
And then the "pre-set" mechanics are a little different from resp.State because List returns multiple entities instead of a single entity, as you've referred to in #1157 (comment). We definitely have room to improve on that.
In the next form of this, I'm hoping we can unexport the *Schema struct fields ✅
| return ListRequestErrorDiagnostics(ctx, allDiags...) | ||
| } | ||
|
|
||
| identitySchema, diags := s.FrameworkServer.ResourceIdentitySchema(ctx, protoReq.TypeName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO, after this PR: we want the flexibility for a list resource in Framework to work with a managed resource type in SDKv2. So we'll revisit this logic.
| return identity, diags | ||
| } | ||
|
|
||
| func (r ListRequest) ToListResult(ctx context.Context, identityVal any, resourceVal any, displayName string) ListResult { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO, after this PR: we want the flexibility for a list resource in Framework to work with a managed resource type in SDKv2. So we'll revisit this helper method.
austinvalle
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this LGTM, I left some general comments and thoughts
| if fwReq.Config == nil { | ||
| return errors.New("Invalid ListResource request: Config cannot be nil") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason we aren't using response diagnostics here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no functional reason. I was on the fence re: error or diagnostics. I learned that Terraform can work with either one, so error struck me as simpler for a request-level nil check.
Now that we have a 👍 on "push a single event with an error diagnostic," we could totally use diagnostics instead. I'm open to that. Any preference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of framework (like the type system for example) uses diagnostics, which are just a summary/detail, so I'd say we should stick to diagnostics unless we can't for whatever reason 👍🏻
| return ListResult(result) | ||
| } | ||
|
|
||
| if result.Identity == nil { // TODO: is result.Identity.Raw.IsNull() a practical concern? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the question would: does Terraform core care if the provider returns a null identity? I would say we probably shouldn't return a null identity unless core says that's acceptable.
In which case we should just check both:
result.Identity == nilbeing the provider likely didn't set anythingresult.Identity.Raw.IsNull()being the provider explicitly set a null value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Terraform currently raises an error when a list result has no identity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably the area we'd want the most feedback on from provider developers right? One thought might be to store the identity/resource schemas on ListResultsStream rather then on the request (also do they need to be exported? 🤔 )
Would a variant of this for multiple list results also we worth doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, today we have a lot of resp.Set which internally use schema data, maybe this would end up being a result.Append variation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
Ready for re-review and auto-merge. TODO items for follow-up:
|
austinvalle
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🚀
Description
This change adds the ListResource RPC.
This is ~80% ready, so I feel okay moving it out of draft mode. I plan to make a round of code review comments, as a guided walkthrough.
Rollback Plan
Changes to Security Controls
None